'use strict';

const Service = require('egg').Service;
const Sequelize = require('sequelize');
const Op = Sequelize.Op;

class PlaylistService extends Service {
  // 歌单列表
  async page(query) {
    const { ctx } = this;
    let config = {
      where:{
        isDel:0
      },
      order:[
        ['createTime', 'DESC']
      ],
      attributes: {
        include: [
          [
            Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM collection
                  WHERE
                      collection.cid = playlist.id
                      AND
                      collection.type = 4
              )`),
            'collectionNum'
          ],
          [
            Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM likes
                  WHERE
                      likes.lid = playlist.id
                      AND
                      likes.type = 4
              )`),
            'likesNum'
          ],
          [
            Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM comment
                  WHERE
                      comment.cid = playlist.id
                      AND
                      comment.type = 4
                      AND
                      comment.isDel = 0
              )`),
            'commentNum'
          ],
          [Sequelize.col('user.account'), 'account'],
          [Sequelize.col('user.nickname'), 'nickname']
        ],
        exclude: ['isDel','delTime','musics'],
      },
      include: [{
        model: ctx.model.User,
        as: 'user',
        duplicating:false,
        required:false,
        attributes: []
      }],
      distinct: true
    };
    if(query.name){
      config.where.name = {
        [Op.like]:`%${query.name}%`
      }
    }
    if(query.uid){
      config.where.uid = query.uid;
    }
    if(!query.pageNO){
      query.pageNO = 1;
    }
    if(!query.pageSize){
      query.pageSize = 10;
    }
    config.offset = (query.pageNO-1)*query.pageSize;
    config.limit = query.pageSize;
    return await ctx.model.Playlist.findAndCountAll(config);
  }

  // 歌单详情
  async detail(query) {
    const { ctx } = this;
    let config = {
      where:{
        isDel:0,
        id:query.id
      },
      attributes: {
        include: [
          [
            Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM collection
                  WHERE
                      collection.cid = playlist.id
                      AND
                      collection.type = 4
              )`),
            'collectionNum'
          ],
          [
            Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM likes
                  WHERE
                      likes.lid = playlist.id
                      AND
                      likes.type = 4
              )`),
            'likesNum'
          ],
          [
            Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM comment
                  WHERE
                      comment.cid = playlist.id
                      AND
                      comment.type = 4
                      AND
                      comment.isDel = 0
              )`),
            'commentNum'
          ],
          [Sequelize.col('user.account'), 'account'],
          [Sequelize.col('user.nickname'), 'nickname']
        ],
        exclude: ['isDel','delTime','musics']
      },
      include: [{
        model: ctx.model.User,
        as: 'user',
        duplicating:false,
        required:false,
        attributes: []
      }],
      distinct: true
    };
    return await ctx.model.Playlist.findOne(config);
  }

  // 歌单删除
  async del(data) {
    const { ctx } = this;
    const t = await ctx.model.transaction();
    try{
      let [collectionDel,likeDel,commentDel,playlistDel] = await Promise.all(
        [
          // 删除收藏
          ctx.model.Collection.destroy({
            where: {
              type:4,
              cid:data.id
            },
            transaction:t
          }),
          // 删除点赞
          ctx.model.Likes.destroy({
            where: {
              type:4,
              lid:data.id
            },
            transaction:t
          }),
          // 删除评论
          ctx.model.Comment.update({
            isDel:1,
            delTime:new Date().getTime()
          },{
            where:{
              type:4,
              cid:data.id
            },
            transaction:t
          }),
          // 删除歌单
          ctx.model.Playlist.update({
            isDel:1,
            delTime:new Date().getTime()
          },{
            where:{
              id:data.id
            },
            transaction:t
          })
        ]
      );
      if(!playlistDel[0]){
        throw new Error('error');
      }
      await t.commit();
      return playlistDel;
    }catch(e){
      await t.rollback();
      return [0];
    }
  }

  // 歌单修改状态
  async status(data) {
    const { ctx } = this;
    return await ctx.model.Playlist.update({
      status:data.status,
      updateTime:new Date().getTime()
    },{
      where:{
        id:data.id
      }
    });
  }

  // 歌单下歌曲列表
  async musiclist(query) {
    const { ctx } = this;
    let config = {
      where:{
        isDel:0,
        id:query.id
      },
      attributes: ['musics']
    };
    let detailResult = await ctx.model.Playlist.findOne(config);
    if(detailResult){
      if(detailResult.musics&&JSON.parse(detailResult.musics) instanceof Array) {
        if (JSON.parse(detailResult.musics).length > 0) {
          if (query.pageNO) {
            let config = {
              where: {
                isDel: 0,
                id: {
                  [Op.in]: JSON.parse(detailResult.musics)
                }
              },
              order: [
                [ 'createTime', 'DESC' ]
              ],
              attributes: {
                include: [
                  [
                    Sequelize.literal(`(
                    SELECT COUNT(*)
                    FROM collection
                    WHERE
                        collection.cid = music.id
                        AND
                        collection.type = 1
                )`),
                    'collectionNum'
                  ],
                  [
                    Sequelize.literal(`(
                    SELECT COUNT(*)
                    FROM likes
                    WHERE
                        likes.lid = music.id
                        AND
                        likes.type = 1
                )`),
                    'likesNum'
                  ],
                  [
                    Sequelize.literal(`(
                    SELECT COUNT(*)
                    FROM comment
                    WHERE
                        comment.cid = music.id
                        AND
                        comment.type = 1
                        AND
                        comment.isDel = 0
                )`),
                    'commentNum'
                  ],
                  [ Sequelize.col('star.name'), 'starName' ],
                  [ Sequelize.col('classify.name'), 'classifyName' ],
                  [ Sequelize.col('album.name'), 'albumName' ]
                ],
                exclude: [ 'isDel', 'delTime', 'lyrics' ],
              },
              include: [
                {
                  model: ctx.model.Star,
                  as: 'star',
                  where: {
                    isDel: 0
                  },
                  duplicating: false,
                  required: false,
                  attributes: []
                },
                {
                  model: ctx.model.Classify,
                  as: 'classify',
                  where: {
                    isDel: 0
                  },
                  duplicating: false,
                  required: false,
                  attributes: []
                },
                {
                  model: ctx.model.Album,
                  as: 'album',
                  where: {
                    isDel: 0
                  },
                  duplicating: false,
                  required: false,
                  attributes: []
                }
              ],
              distinct: true
            };
            if (!query.pageSize) {
              query.pageSize = 10;
            }
            config.offset = (query.pageNO - 1) * query.pageSize;
            config.limit = query.pageSize;
            return await ctx.model.Music.findAndCountAll(config);
          } else {
            let config = {
              where: {
                isDel: 0,
                id: {
                  [Op.in]: JSON.parse(detailResult.musics)
                }
              },
              order: [
                [ 'createTime', 'DESC' ]
              ],
              attributes: {
                include: [
                  [
                    Sequelize.literal(`(
                    SELECT COUNT(*)
                    FROM collection
                    WHERE
                        collection.cid = music.id
                        AND
                        collection.type = 1
                )`),
                    'collectionNum'
                  ],
                  [
                    Sequelize.literal(`(
                    SELECT COUNT(*)
                    FROM likes
                    WHERE
                        likes.lid = music.id
                        AND
                        likes.type = 1
                )`),
                    'likesNum'
                  ],
                  [
                    Sequelize.literal(`(
                    SELECT COUNT(*)
                    FROM comment
                    WHERE
                        comment.cid = music.id
                        AND
                        comment.type = 1
                        AND
                        comment.isDel = 0
                )`),
                    'commentNum'
                  ],
                  [ Sequelize.col('star.name'), 'starName' ],
                  [ Sequelize.col('classify.name'), 'classifyName' ],
                  [ Sequelize.col('album.name'), 'albumName' ]
                ],
                exclude: [ 'isDel', 'delTime', 'lyrics' ],
              },
              include: [
                {
                  model: ctx.model.Star,
                  as: 'star',
                  where: {
                    isDel: 0
                  },
                  duplicating: false,
                  required: false,
                  attributes: []
                },
                {
                  model: ctx.model.Classify,
                  as: 'classify',
                  where: {
                    isDel: 0
                  },
                  duplicating: false,
                  required: false,
                  attributes: []
                },
                {
                  model: ctx.model.Album,
                  as: 'album',
                  where: {
                    isDel: 0
                  },
                  duplicating: false,
                  required: false,
                  attributes: []
                }
              ],
              distinct: true
            };
            return await ctx.model.Music.findAll(config);
          }
        } else {
          if (query.pageNO) {
            return {
              count: 0,
              rows: []
            };
          } else {
            return [];
          }
        }
      }else{
        if (query.pageNO) {
          return {
            count: 0,
            rows: []
          };
        } else {
          return [];
        }
      }
    }else{
      return false;
    }
  }

  // 递归获取评论集合
  async recursiveComment(arr,id){
    const { ctx } = this;
    let config = {
      where:{
        isDel:0,
        pid:id,
        type:4
      },
      attributes: ['id']
    };
    let result = await ctx.model.Comment.findOne(config);
    if(result){
      arr.push(result.id);
      await this.recursiveComment(arr,result.id);
    }
  }

  // 歌单评论列表
  async commentPage(query) {
    const { ctx } = this;
    let config = {
      where:{
        isDel:0,
        cid:query.cid,
        type:4
      },
      order:[
        ['createTime', 'DESC']
      ],
      attributes: {
        include: [
          [
            Sequelize.literal(`(
                      SELECT COUNT(*)
                      FROM likes
                      WHERE
                          likes.lid = comment.id
                          AND
                          likes.type = 5
                  )`),
            'likesNum'
          ],
          [
            Sequelize.literal(`(
                      SELECT COUNT(*)
                      FROM comment AS c
                      WHERE
                          c.pid = comment.id
                          AND
                          c.type = 4
                          AND
                          c.isDel = 0
                  )`),
            'commentNum'
          ],
          [Sequelize.col('user.account'), 'account'],
          [Sequelize.col('user.nickname'), 'nickname']
        ],
        exclude: ['isDel','delTime','type'],
      },
      include: [{
        model: ctx.model.User,
        as: 'user',
        duplicating:false,
        required:false,
        attributes: []
      }],
      distinct: true
    };
    config.where.pid = query.pid?query.pid:0;
    if(!query.pageNO){
      query.pageNO = 1;
    }
    if(!query.pageSize){
      query.pageSize = 10;
    }
    config.offset = (query.pageNO-1)*query.pageSize;
    config.limit = query.pageSize;
    return await ctx.model.Comment.findAndCountAll(config);
  }

  // 歌单评论详情
  async commentDetail(query) {
    const { ctx } = this;
    let config = {
      where:{
        isDel:0,
        id:query.id,
        type:4
      },
      attributes: {
        include: [
          [
            Sequelize.literal(`(
                      SELECT COUNT(*)
                      FROM likes
                      WHERE
                          likes.lid = comment.id
                          AND
                          likes.type = 5
                  )`),
            'likesNum'
          ],
          [
            Sequelize.literal(`(
                      SELECT COUNT(*)
                      FROM comment AS c
                      WHERE
                          c.pid = comment.id
                          AND
                          comment.type = 4
                          AND
                          comment.isDel = 0
                  )`),
            'commentNum'
          ],
          [Sequelize.col('user.account'), 'account'],
          [Sequelize.col('user.nickname'), 'nickname']
        ],
        exclude: ['isDel','delTime','type']
      },
      include: [{
        model: ctx.model.User,
        as: 'user',
        duplicating:false,
        required:false,
        attributes: []
      }]
    };
    return await ctx.model.Comment.findOne(config);
  }

  // 歌单评论删除
  async commentDel(data) {
    const { ctx } = this;
    const t = await ctx.model.transaction();
    try{
      let delArr = [data.id];
      await this.recursiveComment(delArr,data.id);
      let [likeDel,commentDel] = await Promise.all(
        [
          // 删除点赞
          ctx.model.Likes.destroy({
            where: {
              type:5,
              lid:{
                [Op.in]:delArr
              }
            },
            transaction:t
          }),
          // 删除评论
          ctx.model.Comment.update({
            isDel:1,
            delTime:new Date().getTime()
          },{
            where:{
              type:4,
              id:{
                [Op.in]:delArr
              }
            },
            transaction:t
          }),
        ]
      );
      if(!commentDel[0]){
        throw new Error('error');
      }
      await t.commit();
      return commentDel;
    }catch(e){
      await t.rollback();
      return [0];
    }
  }

  // 歌单评论状态修改
  async commentStatus(data) {
    const { ctx } = this;
    return await ctx.model.Comment.update({
      status:data.status,
      updateTime:new Date().getTime()
    },{
      where:{
        id:data.id,
        type:4
      }
    });
  }

  // 获取歌单总数
  async getNum() {
    const { ctx } = this;
    return await ctx.model.Playlist.findOne({
      attributes: [
          [
            Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM playlist
                  WHERE
                      playlist.isDel = 0
              )`),
            'num'
          ]
        ]
    });
  }

  // 播放量排名前十歌单
  async getTopPlaylist(){
    const { ctx } = this;
    let config = {
      where:{
        isDel:0
      },
      offset:0,
      limit:10,
      order:[
        ['playNum', 'DESC']
      ],
      attributes: {
        include: [
          [
            Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM collection
                  WHERE
                      collection.cid = playlist.id
                      AND
                      collection.type = 4
              )`),
            'collectionNum'
          ],
          [
            Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM likes
                  WHERE
                      likes.lid = playlist.id
                      AND
                      likes.type = 4
              )`),
            'likesNum'
          ],
          [
            Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM comment
                  WHERE
                      comment.cid = playlist.id
                      AND
                      comment.type = 4
                      AND
                      comment.isDel = 0
              )`),
            'commentNum'
          ],
          [Sequelize.col('user.account'), 'account'],
          [Sequelize.col('user.nickname'), 'nickname']
        ],
        exclude: ['isDel','delTime','musics'],
      },
      include: [{
        model: ctx.model.User,
        as: 'user',
        duplicating:false,
        required:false,
        attributes: []
      }]
    };
    return await ctx.model.Playlist.findAll(config);
  }
}

module.exports = PlaylistService;
